# Title     : TODO
# Objective : TODO
# Created by: Administrator
# Created on: 2019/7/24

library(ggrepel)
library(optparse)
library(stringr)
library(magrittr)
library(tidyverse)
library(car)

createWhenNoExist <- function(f) {
  !dir.exists(f) && dir.create(f)
}

option_list <- list(
  make_option("--i", default = "AllMet_Raw.txt", type = "character", help = "metabolite data file"),
  make_option("--g", default = "group.txt", type = "character", help = "sample group file"),
  make_option("--config", default = "calculate_config.json", type = "character", help = "config file")
)
opt <- parse_args(OptionParser(option_list = option_list))

args <- commandArgs(trailingOnly = F)
scriptPath <- dirname(sub("--file=", "", args[grep("--file", args)]))
source(str_c(scriptPath, "/base.R"))

configJson <- fromJSON(opt$config)
configJson
isPaired <- configJson$isPaired %>%
  as.logical()
diffMethod <- configJson$method
fcMethod <- configJson$fcMethod
pValue <- configJson$pValue  %>%
  as.numeric()
pValue
useFdr <- configJson$useFdr %>%
  as.logical()
tmpFdr <- configJson$fdr %>%
  as.numeric()
fdr <- if (useFdr) {
  tmpFdr
}else 1
log2FC <- configJson$log2FC %>%
  as.numeric()

options(digits = 3)

isT <- function(data1, data2) {
  var1 <- var(data1)
  if (var1 == 0) {
    return(F)
  }
  d1Test <- shapiro.test(data1)
  d1P <- d1Test$p.value
  if (d1P < 0.05) {
    return(F)
  }
  var2 <- var(data2)
  if (var2 == 0) {
    return(F)
  }
  d2Test <- shapiro.test(data2)
  d2P <- d2Test$p.value
  if (d2P < 0.05) {
    return(F)
  }
  data <- tibble(value = c(data1, data2), group = factor(c(rep(1, length(data1)), rep(2, length(data2)))))
  bTest <- leveneTest(value ~ group, data)
  bp <- bTest$`Pr(>F)`[1]
  if (bp < 0.05) {
    return(F)
  }
  return(T)
}

my.test <- function(data1, data2, paired, method) {
  p <- 0
  curMethod <- method
  if (curMethod == "auto") {
    b <- isT(data1, data2)
    if (b) {
      curMethod <- "t"
    }else {
      curMethod <- "u"
    }
  }

  if (curMethod == "u") {
    test <- wilcox.test(data1, data2, paired = paired)
    p <- test$p.value
    curMethod <- "wilcox.test"
  }else if (curMethod == "t") {
    tryCatch({
      test <- t.test(data1, data2, paired = paired,var.equal = T)
      p <- test$p.value
    }, error = function(e) {
      p <- 1
    })

    curMethod <- "t.test"
  }
  if (is.na(p)) {
    p <- 1
  }
  list(p = p, method = curMethod)
}

my.fc <- function(data1, data2, method) {
  fc <- 0
  curMethod <- method
  if (curMethod == "auto") {
    b <- isT(data1, data2)
    if (b) {
      curMethod <- "mean"
    }else {
      curMethod <- "median"
    }
  }

  if (curMethod == "median") {
    median1 <- median(data1)
    median2 <- median(data2)
    fc <- median2 / median1
  }else if (curMethod == "mean") {
    mean1 <- mean(data1)
    mean2 <- mean(data2)
    fc <- mean2 / mean1
  }
  if (is.nan(fc)) {
    fc <- 1
  }
  list(fc = fc, method = curMethod)
}

originalData <- read_tsv(opt$i) %>%
  rename(Metabolite = 1)

sampleInfo <- read_tsv(opt$g) %>%
  rename(SampleID = Sample) %>%
  mutate(ClassNote = as.character(ClassNote))

sampleIds <- sampleInfo$SampleID

classNotes <- unique(sampleInfo$ClassNote)
cn <- combn(classNotes, 2)
for (i in 1:ncol(cn)) {
  row <- cn[, i]
  group1Name <- row[1]
  group2Name <- row[2]
  group1Sample <- sampleInfo %>%
    filter(ClassNote == group1Name) %>%
    .$SampleID
  group2Sample <- sampleInfo %>%
    filter(ClassNote == group2Name) %>%
    .$SampleID
  if (isPaired) {
    group1Sample <- sampleInfo %>%
      filter(ClassNote == group1Name) %>%
      arrange(Pair_ID) %>%
      .$SampleID
    group2Sample <- sampleInfo %>%
      filter(ClassNote == group2Name) %>%
      arrange(Pair_ID) %>%
      .$SampleID
  }
  allData <- originalData %>%
    select(c("Metabolite", sampleIds)) %>%
    rowwise() %>%
    do({
      result <- as.data.frame(.)
      group1Data <- result[group1Sample] %>% unlist
      group2Data <- result[group2Sample] %>% unlist
      mean1Name <- paste0(group1Name, ".Mean")
      result[, mean1Name] <- mean(group1Data)
      mean2Name <- paste0(group2Name, ".Mean")
      result[, mean2Name] = mean(group2Data)
      median1Name <- paste0(group1Name, ".Median")
      result[, median1Name] <- median(group1Data)
      median2Name <- paste0(group2Name, ".Median")
      result[, median2Name] = median(group2Data)
      result[, paste0(group1Name, ".SD")] = sd(group1Data)
      result[, paste0(group2Name, ".SD")] = sd(group2Data)
      iqr11 <- quantile(group1Data, 0.25)
      iqr12 <- quantile(group1Data, 0.75)
      iqr1 <- paste0("[", iqr11, ",", iqr12, "]")
      iqr1Name <- paste0(group1Name, ".IQR")
      result[, iqr1Name] <- iqr1
      iqr21 <- quantile(group2Data, 0.25)
      iqr22 <- quantile(group2Data, 0.75)
      iqr2 <- paste0("[", iqr21, ",", iqr22, "]")
      iqr2Name <- paste0(group2Name, ".IQR")
      result[, iqr2Name] <- iqr2
      rs <- my.test(group1Data, group2Data, isPaired, diffMethod)
      result$P <- rs$p
      result$test.method <- rs$method
      result$FC <- my.fc(group1Data, group2Data, fcMethod)$fc
      result
    }) %>%
    select(-c(sampleInfo$SampleID)) %>%
    as.data.frame()

  print("=1=")
  print(head(allData))

  data <- allData %>%
    mutate(FDR = p.adjust(P, method = "fdr")) %>%
    select(-FC, everything()) %>%
    mutate(log2FC = log(FC, 2)) %>%
    select(-"test.method", everything(), "test.method")

  print("=2=")
  print(head(data))

  parent <- paste0("./")
  allFileName <- paste0(parent, "/AllMet_Test.csv")
  write.csv(data, allFileName, row.names = FALSE)
}

finalDf <- read_csv("AllMet_Test.csv") %>%
  rowwise() %>%
  do({
    result <- as.data.frame(.)
    p <- result[1, "P"]
    logFc <- result[1, "log2FC"]
    q <- result[1, "FDR"]
    value <- if (p < pValue & q < fdr & abs(logFc) > log2FC) {
      1
    }else 0
    result$IS_Uni_P_Sig <- value
    result
  }) %>%
  filter(IS_Uni_P_Sig == 1) %>%
  select(-c("IS_Uni_P_Sig"))

outFileName <- paste0(parent, "/Diff_Met_Test.csv")
write_csv(finalDf, outFileName)

diffData <- finalDf %>%
  select(c("Metabolite"))

write_csv(diffData, "Diff_Metabolite.csv")















